package com.example.utils;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.atomic.AtomicInteger;

//购物订单高并发生成30位长度唯一流水编号，包含生成时间、地址、国别，唯一性：不能重复
/*
 * 时间戳（14位）：yyyyMMddHHmmss 格式的时间戳，精确到秒
 * 国别代码（3位）：ISO 三位字母国家代码（如 CHN=中国，USA=美国）
 * 地址编码（5位）：可使用城市或仓库编码，建议映射为数字（如北京=00100）
 * 序列号（8位）：同一时间 + 地址下的自增序列，防止冲突
 *总长度：30位*/
public class OrderNoGenerator {
    // 3位国别码
    private final String countryCode;
    // 5位地址码
    private final String locationCode;
    // 自增序列号，使用AtomicInteger保证线程安全
    private final AtomicInteger sequence = new AtomicInteger(0);
    // 日期格式化工具，用于生成时间戳
    private final SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");

    /**
     * 构造函数，初始化国别码和地址码
     *
     * @param countryCode  3位国别码
     * @param locationCode 5位地址码
     * @throws IllegalArgumentException 如果国别码不是3位或地址码不是5位，则抛出此异常
     */
    public OrderNoGenerator(String countryCode, String locationCode) {
        if (countryCode.length() != 3 || locationCode.length() != 5) {
            throw new IllegalArgumentException("国别码必须为3位，地址码必须为5位");
        }
        this.countryCode = countryCode;
        this.locationCode = locationCode;
    }

    public static void main(String[] args) {
        // 创建OrderNoGenerator实例，参数为国别码和地址码
        OrderNoGenerator generator = new OrderNoGenerator("CHN", "00100"); // 北京中国
        // 循环生成并打印10个订单编号
        for (int i = 0; i < 10; i++) {
            System.out.println(generator.generate());
        }
    }

    /**
     * 生成并返回一个唯一的订单编号
     *
     * @return 生成的30位订单编号字符串
     */
    public synchronized String generate() {
        // 获取当前时间的时间戳
        String timestamp = sdf.format(new Date());
        // 序列号自增并取模，确保序列号为8位
        int seq = sequence.incrementAndGet() % 100000000;
        // 按照规定格式组合时间戳、国别码、地址码和序列号，生成最终的订单编号
        return String.format("%s%s%s%08d", timestamp, countryCode, locationCode, seq);
    }
}

